package com.mc.read.adminapi.websocket;

import com.alibaba.fastjson.JSON;
import com.mc.read.dao.mapper.BookinformationMapper;
import com.mc.read.dao.mapper.ChatrecordMapper;
import com.mc.read.dao.models.Bookinformation;
import com.mc.read.dao.models.Chatrecord;
import com.mc.read.dao.vo.Message;
import com.mc.read.vo.respose.BaseRespose;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * WebSocket 聊天服务端（多个的）
 *
 * @see ServerEndpoint WebSocket服务端 需指定端点的访问路径
 * @see Session   WebSocket会话对象 通过它给客户端发送消息
 */

@Service
@ServerEndpoint("/chat/{bookid}")
public class WebSocketChatServer {
//    @Autowired
//    ChatrecordMapper chatrecordMapper;
//    @Autowired
//    BookinformationMapper bookinformationMapper;


    BookinformationMapper bookinformationMapper = (BookinformationMapper) ApplicationContextRegister.getApplicationContext().getBean(BookinformationMapper.class);

    ChatrecordMapper chatrecordMapper = (ChatrecordMapper) ApplicationContextRegister.getApplicationContext().getBean(ChatrecordMapper.class);

    // 使用map来收集session，key为roomName，value为同一个房间的用户集合
    // concurrentMap的key不存在时报错，不是返回null
    private static final Map<Integer, Set<Session>> rooms = new ConcurrentHashMap();

    /**
     * 全部在线会话  PS: 基于场景考虑 这里使用线程安全的Map存储会话对象。
     */
//    private static Map<String, Session> onlineSessions = new ConcurrentHashMap<>();


    /**
     * 当客户端打开连接
     */
    @OnOpen
    public void onOpen(@PathParam("bookid") Integer bookid, Session session) {
        BaseRespose baseRespose = new BaseRespose();
        if (ObjectUtils.isEmpty(bookid)) {
            try {
                session.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (bookid != 0) {
            Bookinformation bookinformation = bookinformationMapper.selectByPrimaryKey(bookid);
            if (ObjectUtils.isEmpty(bookinformation)) {
                try {
                    session.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        if (!rooms.containsKey(bookid)) {
            // 创建房间不存在时，创建房间
            Set<Session> room = new HashSet<Session>();
            // 添加用户
            room.add(session);
            rooms.put(bookid, room);
        } else {
            // 房间已存在，直接添加用户到相应的房间
            rooms.get(bookid).add(session);
        }
        Message message = new Message();
        message.setType(1);
        List<Message> chatrecordList = chatrecordMapper.selectTop100(bookid);
        message.setMessageList(chatrecordList);
        sendMessageToAll(bookid, JSON.toJSONString(message));

    }

    /**
     * 当客户端发送消息：1.获取它的用户名和消息 2.发送消息给所有人
     * <p>
     * PS: 这里约定传递的消息为JSON字符串 方便传递更多参数！
     */
    @OnMessage
    public void onMessage(@PathParam("bookid") Integer bookid, Session session, String jsonStr) {
        System.out.println(jsonStr);
        Message message = JSON.parseObject(jsonStr, Message.class);
        message.setNowtime(new Date());
        message.setType(2);
        Chatrecord chatrecord = new Chatrecord();
        chatrecord.setBookid(bookid);
        chatrecord.setMsg(message.getMsg());
        chatrecord.setCreatedate(message.getNowtime());
        chatrecord.setUserid(message.getUserid());
        chatrecord.setUsername(message.getUsername());
        chatrecordMapper.insertSelective(chatrecord);
        sendMessageToAll(bookid, JSON.toJSONString(message));
    }

    /**
     * 当关闭连接：1.移除会话对象 2.更新在线人数
     */
    @OnClose
    public void onClose(@PathParam("bookid") Integer bookid, Session session) {
        System.out.println("关闭连接");
        try {
            rooms.get(bookid).remove(session);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 当通信发生异常：打印错误日志
     */
    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }

    /**
     * 公共方法：发送信息给所有人
     */
    private static void sendMessageToAll(Integer bookid, String msg) {
        try {
            Set<Session> sessions = new HashSet<>();
            sessions.addAll(rooms.get(bookid));
            if (!ObjectUtils.isEmpty(sessions)) {
                for (Session session : sessions) {
                    try {
                        if (session.isOpen()) {
                            session.getBasicRemote().sendText(msg);
                        } else {
                            rooms.get(bookid).remove(session);
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 按照房间名进行广播
    public static void broadcast(String roomName, String msg) throws Exception {

    }


}
